///////////////////////////////////////////////////////////////////////////////////////////////////
// Company: <Ning>
//
// File: gsmpbx.v
// File history:
//      <0.1>: <2013-1-14>: <draft>
//      <Revision number>: <Date>: <Comments>
//      <Revision number>: <Date>: <Comments>
//
// Description: 
//
// <GSM PBX data and control FPGA>
//
// Targeted device: <Family::ProASIC3> <Die::A3P060> <Package::100 VQFP>
// Author: <Wang Ning>
//
/////////////////////////////////////////////////////////////////////////////////////////////////// 
//`timescale <time_units> / <precision>

module gsmpbx(
    pcm_clk,
    pcm_fsync,
    pcm_tx,
    pcm_rx,
    spi_cs,
    spi_clk,
    spi_sdo,
    spi_sdi,
    //cpld,
    drx,
    dtx,
    fsync,
    mclk
);
output pcm_clk;
output [7:0] pcm_fsync;
input [7:0] pcm_tx;
output [7:0] pcm_rx;
output [7:0] spi_cs;
output [7:0] spi_clk;
input [7:0] spi_sdo;
output [7:0] spi_sdi;
//output [5:0] cpld;
input drx;
output dtx;
input fsync;
input mclk;



assign pcm_clk = mclk;

wire mfs;
assign mfs = fsync;

wire mdrx;
assign mdrx = drx;

reg [8:0] mc;

// counter for spi cs
reg [8:0] xc;
reg [8:0] yc;
reg [7:0] xcs;
reg [7:0] ycs;

// select pcm channel.
reg [7:0] pcm_sel;
reg [7:0] spi_sel;

reg [6:0] pcm_fs;


// first channel fync same as the main fync
assign pcm_fsync[0] = mfs;
assign pcm_fsync[7:1] = pcm_fs[6:0];

assign spi_cs = xcs & ycs;

assign dtx = (pcm_tx[0] | pcm_sel[0]) & (pcm_tx[1] | pcm_sel[1]) & (pcm_tx[2] | pcm_sel[2]) & (pcm_tx[3] | pcm_sel[3]) 
                & (pcm_tx[4] | pcm_sel[4]) & (pcm_tx[5] | pcm_sel[5]) & (pcm_tx[6] | pcm_sel[6]) & (pcm_tx[7] | pcm_sel[7])
                & (spi_sdo[0] | spi_sel[0]) & (spi_sdo[1] | spi_sel[1]) & (spi_sdo[2] | spi_sel[2]) & (spi_sdo[3] | spi_sel[3])
                & (spi_sdo[4] | spi_sel[4]) & (spi_sdo[5] | spi_sel[5]) & (spi_sdo[6] | spi_sel[6]) & (spi_sdo[7] | spi_sel[7]);


assign pcm_rx[0] = mdrx | pcm_sel[0];
assign pcm_rx[1] = mdrx | pcm_sel[1];
assign pcm_rx[2] = mdrx | pcm_sel[2];
assign pcm_rx[3] = mdrx | pcm_sel[3];
assign pcm_rx[4] = mdrx | pcm_sel[4];
assign pcm_rx[5] = mdrx | pcm_sel[5];
assign pcm_rx[6] = mdrx | pcm_sel[6];
assign pcm_rx[7] = mdrx | pcm_sel[7];

assign spi_sdi[0] = mdrx | spi_sel[0];
assign spi_sdi[1] = mdrx | spi_sel[1];
assign spi_sdi[2] = mdrx | spi_sel[2];
assign spi_sdi[3] = mdrx | spi_sel[3];
assign spi_sdi[4] = mdrx | spi_sel[4];
assign spi_sdi[5] = mdrx | spi_sel[5];
assign spi_sdi[6] = mdrx | spi_sel[6];
assign spi_sdi[7] = mdrx | spi_sel[7];

assign spi_clk[0] = ~mclk | spi_sel[0];
assign spi_clk[1] = ~mclk | spi_sel[1];
assign spi_clk[2] = ~mclk | spi_sel[2];
assign spi_clk[3] = ~mclk | spi_sel[3];
assign spi_clk[4] = ~mclk | spi_sel[4];
assign spi_clk[5] = ~mclk | spi_sel[5];
assign spi_clk[6] = ~mclk | spi_sel[6];
assign spi_clk[7] = ~mclk | spi_sel[7];


// receive data at negedge.
always @(negedge mclk)
begin
    if (mfs == 9'd1) mc <= 9'd0;
    else if (mc < 9'd511) mc <= mc + 9'd1;
end

// send data at posedge
always @(posedge mclk)
begin

    xc <= mc + 9'd1;
	yc <= mc;

    // fsync
    case (mc)
        7:  pcm_fs[0] <= 1;
        15: pcm_fs[1] <= 1;
        23: pcm_fs[2] <= 1;
        31: pcm_fs[3] <= 1;
        39: pcm_fs[4] <= 1;
        47: pcm_fs[5] <= 1;
        55: pcm_fs[6] <= 1;
        default: pcm_fs[6:0] <= 7'h0;
    endcase

    // pcm
    case (mc[8:3])
        0: pcm_sel <= 8'b11111110;
        1: pcm_sel <= 8'b11111101;
        2: pcm_sel <= 8'b11111011;
        3: pcm_sel <= 8'b11110111;
        4: pcm_sel <= 8'b11101111;
        5: pcm_sel <= 8'b11011111;
        6: pcm_sel <= 8'b10111111;
        7: pcm_sel <= 8'b01111111;
        default: pcm_sel <= 8'b11111111;
    endcase

    // SPI
    case (mc[8:3])

        6'd8,6'd9, 6'd24,6'd25, 6'd40,6'd41: begin
            spi_sel <= 8'b11111110;
        end

        6'd10,6'd11, 6'd26,6'd27, 6'd42,6'd43: begin
            spi_sel <= 8'b11111101;
        end

        6'd12,6'd13, 6'd28,6'd29, 6'd44,6'd45: begin
            spi_sel <= 8'b11111011;
        end

        6'd14,6'd15, 6'd30,6'd31, 6'd46,6'd47: begin
            spi_sel <= 8'b11110111;
        end

        6'd16,6'd17, 6'd32,6'd33, 6'd48,6'd49: begin
            spi_sel <= 8'b11101111;
        end

        6'd18,6'd19, 6'd34,6'd35, 6'd50,6'd51: begin
            spi_sel <= 8'b11011111;
        end

        6'd20,6'd21, 6'd36,6'd37, 6'd52,6'd53: begin
            spi_sel <= 8'b10111111;
        end

        6'd22,6'd23, 6'd38,6'd39, 6'd54,6'd55: begin
            spi_sel <= 8'b01111111;
        end

        default: begin
            spi_sel <= 8'b11111111;
        end

    endcase
end
	
always @(negedge mclk)
begin
    case (xc[8:3])

        6'd8,6'd9, 6'd24,6'd25, 6'd40,6'd41: begin
            xcs <= 8'b11111110;
        end

        6'd10,6'd11, 6'd26,6'd27, 6'd42,6'd43: begin
            xcs <= 8'b11111101;
        end

        6'd12,6'd13, 6'd28,6'd29, 6'd44,6'd45: begin
            xcs <= 8'b11111011;
        end

        6'd14,6'd15, 6'd30,6'd31, 6'd46,6'd47: begin
            xcs <= 8'b11110111;
        end

        6'd16,6'd17, 6'd32,6'd33, 6'd48,6'd49: begin
            xcs <= 8'b11101111;
        end

        6'd18,6'd19, 6'd34,6'd35, 6'd50,6'd51: begin
            xcs <= 8'b11011111;
        end

        6'd20,6'd21, 6'd36,6'd37, 6'd52,6'd53: begin
            xcs <= 8'b10111111;
        end

        6'd22,6'd23, 6'd38,6'd39, 6'd54,6'd55: begin
            xcs <= 8'b01111111;
        end

        default: begin
            xcs <= 8'b11111111;
        end
    endcase

    case (yc[8:3])

        6'd8,6'd9, 6'd24,6'd25, 6'd40,6'd41: begin
            ycs <= 8'b11111110;
        end

        6'd10,6'd11, 6'd26,6'd27, 6'd42,6'd43: begin
            ycs <= 8'b11111101;
        end

        6'd12,6'd13, 6'd28,6'd29, 6'd44,6'd45: begin
            ycs <= 8'b11111011;
        end

        6'd14,6'd15, 6'd30,6'd31, 6'd46,6'd47: begin
            ycs <= 8'b11110111;
        end

        6'd16,6'd17, 6'd32,6'd33, 6'd48,6'd49: begin
            ycs <= 8'b11101111;
        end

        6'd18,6'd19, 6'd34,6'd35, 6'd50,6'd51: begin
            ycs <= 8'b11011111;
        end

        6'd20,6'd21, 6'd36,6'd37, 6'd52,6'd53: begin
            ycs <= 8'b10111111;
        end

        6'd22,6'd23, 6'd38,6'd39, 6'd54,6'd55: begin
            ycs <= 8'b01111111;
        end

        default: begin
            ycs <= 8'b11111111;
        end
    endcase
end


endmodule

